import { Component, OnInit, OnDestroy } from '@angular/core';
import { Http } from '@angular/http';
import { DatePipe } from '@angular/common';
import { List } from 'linqts';
import { Subject } from 'rxjs/Rx';
import { MatrixStateGroupService } from '../../../service/matrix-state-group.service';
import { MatrixStateService } from '../../../service/matrix-state.service';
import { DataSourceService } from '../../../service/data-source/data-source.service';
import { ApplicationService } from '../../../service/application.service';
import { TagService } from '../../../service/tag.service';
import { TagMapService } from '../../../service/tag-map.service';
import { Farm } from '../../../entity/farm.model';
import { MatrixState } from '../../../entity/matrix_state.model';
import { Tag } from '../../../entity/tag.model';
import { MatrixStateGroup } from '../../../entity/matrix-state-group.model';
import { MatrixRelation } from '../../../entity/matrix-relation.model';

import { MatrixTurbine } from './matrix-turbine';
import { MatrixFarm } from './matrix-farm';
import { MatrixStateGroupTotal } from './matrix-state-group-total';
import { ChangeArgs } from './farm-multi-selector/farm-multi-selector.component';
import { MatrixStateTotal } from './matrix-state-total';
import { DeviceService } from '../../../service/device.service';
import { Device } from '../../../entity/device.model';
import { NzMessageService } from 'ng-zorro-antd';
import { InterceptorService } from '../../../service/interceptor/interceptor-service';

@Component({
  selector: 'app-turbine-matrix',
  templateUrl: './turbine-matrix.component.html',
  styleUrls: ['./turbine-matrix.component.css'],
})
export class TurbineMatrixComponent implements OnInit, OnDestroy {
  public selectedTag: Tag;
  public farms: Farm[];
  public matrixTurbines: MatrixTurbine[] = [];
  public matrixTags: Tag[];
  public matrixFarms: MatrixFarm[] = [];
  public matrixStateGroupMap: MatrixStateGroupMap = {};
  public matrixStateGroupTotals: MatrixStateGroupTotal[] = [];
  private matrixRelationMap: MatrixRelationMap;
  private dataSource: DataSourceService;

  constructor(
    private http: InterceptorService,
    private datePipe: DatePipe,
    private application: ApplicationService,
    private tagService: TagService,
    private tagMapService: TagMapService,
    private deviceService: DeviceService,
    private matrixStateGroupService: MatrixStateGroupService,
    private matrixStateService: MatrixStateService,
    private _message: NzMessageService
  ) {
    this.farms = this.application.currentUserFarms.filter(farm => farm.farmCategory === 'winfarm');
    this.farms.map(o => o.isChecked = true);
  }
  public ngOnInit() {
    this.initData();
  }
  public ngOnDestroy() {
    if (this.dataSource) {
      this.dataSource.dispose();
      this.dataSource = null;
    }
  }

  /**
   * 初始化数据
   *
   * @memberof TurbineMatrixComponent
   */
  private initData() {
    const id = this._message.loading('数据正在加载中', { nzDuration: 0 }).messageId;
    let tagGet = this.tagService.getTagsByTagSet('02');
    let turbGet = this.deviceService.getDevices();
    let stateGroupGet = this.matrixStateGroupService.getMatrixStateGroups();
    let stateGet = this.matrixStateService.getMatrixStates();
    Promise.all([tagGet, turbGet, stateGroupGet, stateGet])
      .then(resArray => {
        this._message.remove(id);
        let tags = resArray[0] ? resArray[0] : [];
        let turbines = resArray[1] ? resArray[1] : [];
        let states = resArray[3] ? resArray[3] : [];
        let stateGroups = resArray[2] ? resArray[2] : [];
        this.matrixTags = tags;

        if (tags !== null && tags.length > 0) {
          let tag = tags.find(o => o.tagCode.startsWith('TurbineStatus'));
          this.selectedTag = tag != null ? tag : tags[0];
        }
        this.initMatrixStateGroupMap(stateGroups, states);
        this.createMatrixTurbines(turbines);
        this.createMatrixFarms(this.farms, this.matrixTurbines);
        //根据选中的Tag请求矩阵的映射关系
        if (this.selectedTag != null) {
          this.initMatrixRelationMap(this.selectedTag);
        }
      })
      .catch(error => {
        this._message.remove(id);
        if (this.application.appConfigData.isShowErr) {
          this._message.info('数据初始化失败' + error, { nzDuration: 3000 });
        }

        //console.log(error);
      });
  }

  /**
   * 初始化状态分组和矩阵状态映射
   *
   * @param {MatrixState[]} states
   * @memberof TurbineMatrixComponent
   */
  private initMatrixStateGroupMap(groups: MatrixStateGroup[], states: MatrixState[]) {
    groups.forEach(matrixStateGroup => {
      let matrixStateMap: MatrixStateMap = {};
      let matrixStates = states.filter(o => o.stateGroupId == matrixStateGroup.stateGroupId);
      if (matrixStates) {
        matrixStates = matrixStates.sort((a, b) => {
          if (a.stateSeq == null && b.stateSeq != null) {
            return 0;
          }
          if (b.stateSeq == null && a.stateSeq != null) {
            return 1;
          }
          if (b.stateSeq == null && a.stateSeq == null) {
            return 0;
          }
          if (a.stateSeq > b.stateSeq) {
            return 1;
          } else {
            return 0;
          }
        });

        matrixStates.forEach(state => {
          matrixStateMap[state.stateId] = state;
        });
      }
      this.matrixStateGroupMap[matrixStateGroup.stateGroupId] = {
        group: matrixStateGroup,
        state: matrixStateMap,
      };
    });

  }

  /**
   * 初始化风机映射
   *
   * @param {Tag} tag
   * @memberof TurbineMatrixComponent
   */
  private initMatrixRelationMap(tag: Tag) {
    this.matrixStateGroupTotals = [];
    this.matrixRelationMap = {};

    //根据测点Id查询矩阵中的配置关系
    this.tagMapService.getMatrixRelationByTagId(tag.tagId)
      .then(relations => {
        if (!relations) { return false; };
        relations.forEach(relation => {
          this.matrixRelationMap[relation.modelId] = relation;
        });
        this.initMatrixTurbinesMatrixState();
        this.initMatrixFarmsMatrixState();
        this.initMatrixStateGroupTotals(relations);
        this.subscribeMatrix(tag);

      })
      .catch(error => {
        if (this.application.appConfigData.isShowErr) {
          this._message.info('查询矩阵中的配置关系' + error, { nzDuration: 3000 });
        }

        //console.log(error);
      });
  }

  private initMatrixTurbinesMatrixState() {
    //为风机设置状态分组
    this.matrixTurbines.forEach(turbine => {
      try {
        turbine.stateGroupId = null;
        turbine.stateId = null;
        turbine.stateColor = 'transparent';
        let relation = this.matrixRelationMap[turbine.modelId];
        if (relation != null) {
          turbine.stateGroupId = relation.stateGroupId;
        }
      }
      catch (error) {
        console.log(error);
      }
    });
  }
  private initMatrixFarmsMatrixState() {
    //为风场设置状态分组
    this.matrixFarms.forEach(farm => {
      farm.stateGroupTotals = [];
      let turbineList = new List(farm.devices);
      let stateGroups = turbineList.GroupBy(g => g.stateGroupId, m => m);
      //console.log(turbineList, stateGroups, this.matrixStateGroupMap)
      let stateGroupIds = Object.getOwnPropertyNames(stateGroups);
      stateGroupIds.forEach(stateGroupId => {
        try {
          if (stateGroupId != 'null') {
            let groupId = Number.parseInt(stateGroupId);
            if (this.matrixStateGroupMap[groupId] != null) {
              let matrixStateGroup = this.matrixStateGroupMap[groupId].group;
              if (matrixStateGroup) {
                let matrixStateGroupTotal: MatrixStateGroupTotal = {
                  groupName: matrixStateGroup.stateGroupName,
                  groupId: matrixStateGroup.stateGroupId,
                  stateTotals: [],
                  total: turbineList.Count(o => o.stateGroupId === groupId),
                  isChecked: true,
                };
                let matrixStatesMap = this.matrixStateGroupMap[groupId].state;
                if (matrixStatesMap) {
                  let stateIds = Object.getOwnPropertyNames(matrixStatesMap);
                  stateIds.forEach(id => {
                    if (id != 'null') {
                      let stateId = Number.parseInt(id);
                      if (matrixStatesMap[stateId]) {
                        matrixStateGroupTotal.stateTotals.push({
                          stateId: matrixStatesMap[stateId].stateId,
                          stateGroupId: matrixStatesMap[stateId].stateGroupId,
                          stateName: matrixStatesMap[stateId].stateName,
                          stateColor: matrixStatesMap[stateId].stateColor,
                          stateTotal: 0,
                          isChecked: matrixStatesMap[stateId].unChecked,
                        });
                      }
                    }

                  })
                }
                farm.stateGroupTotals.push(matrixStateGroupTotal);
              }
            }
          }
        }
        catch (error) {
          console.log(error);
        }
      });
    });
  }
  private initMatrixStateGroupTotals(relations: MatrixRelation[]) {
    let turbineList = new List(this.matrixTurbines);

    let sateGroupIds = new List(relations.map(o => o.stateGroupId)).Distinct();
    sateGroupIds.ForEach(groupid => {
      if (this.matrixStateGroupMap[groupid]) {
        let matrixStateGroup = this.matrixStateGroupMap[groupid].group;
        let total: MatrixStateGroupTotal = {
          groupName: matrixStateGroup.stateGroupName,
          groupId: matrixStateGroup.stateGroupId,
          total: turbineList.Count(o => o.stateGroupId == groupid),
          isChecked: true,
          stateTotals: [],
        }
        let matrixStatesMap = this.matrixStateGroupMap[groupid].state;
        let stateIds = Object.getOwnPropertyNames(matrixStatesMap);
        stateIds.forEach(id => {
          let stateId = Number.parseInt(id);
          total.stateTotals.push({
            stateId: matrixStatesMap[stateId].stateId,
            stateGroupId: matrixStatesMap[stateId].stateGroupId,
            stateName: matrixStatesMap[stateId].stateName,
            stateColor: matrixStatesMap[stateId].stateColor,
            stateTotal: 0,
            isChecked: matrixStatesMap[stateId].unChecked,
          });
        });
        this.matrixStateGroupTotals.push(total);

      }
    });



  }
  private subscribeMatrix(tag: Tag) {
    if (this.dataSource) {
      this.dataSource.dispose();
      this.dataSource = null;
    };
    // console.log(this.matrixTurbines,this.matrixStateGroupMap);
    //订阅矩阵数据
    this.dataSource = new DataSourceService(this.http, this.datePipe);
    this.dataSource.matrix({ tagId: tag.tagId, farmIds: this.farms.map(o => o.farmId) })
      .subscribe(
        next => {
          next.forEach(matrixData => {
            let turbine = this.matrixTurbines.find(turbine => turbine.deviceId == matrixData.deviceId);
            if (turbine != null && turbine.stateGroupId != null) {
              console.log(turbine);
              turbine.stateId = matrixData.stateId;
              if (matrixData.stateId != 0) {
                let stateMap = this.matrixStateGroupMap[turbine.stateGroupId].state;
                if (stateMap && stateMap[matrixData.stateId]) {
                  turbine.stateColor = stateMap[matrixData.stateId].stateColor;
                }
                else {
                  turbine.stateColor = 'transparent'
                }
              }
              else {
                turbine.stateColor = 'transparent'
              }
            }

          });
          this.matrixFarms.forEach(farm => {
            let turbineList = new List(farm.devices);
            farm.stateGroupTotals.forEach(stateGroup => {
              stateGroup.stateTotals.forEach(state => {
                state.stateTotal = turbineList.Count(o => o.stateGroupId == stateGroup.groupId && o.stateId == state.stateId);
              });
            });
          });
          let turbinelist = new List(this.matrixTurbines);
          this.matrixStateGroupTotals.forEach(group => {
            group.stateTotals.forEach(state => {
              state.stateTotal = turbinelist.Count(o => o.stateGroupId == group.groupId && o.stateId == state.stateId);
            });
          });
          this.filter();
        },
        error => {
          console.log(error);
        }
      );
  }

  /**
   * 创建矩阵风机
   *
   * @param {Turbine[]} turbines
   * @memberof TurbineMatrixComponent
   */
  private createMatrixTurbines(devices: Device[]) {
    devices.forEach(device => {
      if (device.deviceCategoryId === 1 || device.deviceCategoryId === 4) {
        let name = device.deviceName.replace('#', '');
        this.matrixTurbines.push({
          farmId: device.farmId,
          deviceId: device.deviceId,
          deviceName: name,
          modelId: device.modelId,
          isChecked: true,
          stateColor: 'transparent',
          deviceCategoryId: device.deviceCategoryId,
        });
      }
    });
  }
  /**
   * 创建矩阵风场
   *
   * @param {Farm[]} farms
   * @param {MatrixTurbine[]} turbines
   * @memberof TurbineMatrixComponent
   */
  private createMatrixFarms(farms: Farm[], turbines: MatrixTurbine[]) {
    farms.forEach(farm => {
      let matrixFarm: MatrixFarm = {
        farmId: farm.farmId,
        farmName: farm.farmName,
        devices: turbines.filter(o => o.farmId === farm.farmId),
        stateGroupTotals: [],
        isChecked: true,
      }
      this.matrixFarms.push(matrixFarm);
    })
  }
  /**
   * 测点选中项发生变化
   *
   * @param {Tag} args
   * @memberof TurbineMatrixComponent
   */
  public onTagSelectedChange(tag: Tag) {
    this.selectedTag = tag;
    this.initMatrixRelationMap(this.selectedTag);
  }
  /**
   * 风场选中项发生改变
   *
   * @param {ChangeArgs} args
   * @memberof TurbineMatrixComponent
   */
  public onFarmSelectedChange(args: ChangeArgs) {
    args.selected.forEach(farm => {
      let index = this.matrixFarms.findIndex(o => o.farmId === farm.farmId);
      this.matrixFarms[index].isChecked = true;
    });
    args.unSelected.forEach(farm => {
      let index = this.matrixFarms.findIndex(o => o.farmId === farm.farmId);
      this.matrixFarms[index].isChecked = false;
    });
  }

  /**
   *
   *
   * @param {MatrixTotalChangeArgs} args
   * @memberof TurbineMatrixComponent
   */
  public onMatrixStateSelectedChange(args: MatrixStateGroupTotal[]) {
    args.forEach(arg => {
      this.matrixFarms.forEach(farm => {
        let farmStateGroup = farm.stateGroupTotals.find(stateGroup => stateGroup.groupId == arg.groupId);
        if (farmStateGroup != null) {
          farmStateGroup.isChecked = arg.isChecked;
          arg.stateTotals.forEach(state => {
            let farmStateTotal = farmStateGroup.stateTotals.find(farmState => farmState.stateId == state.stateId);
            if (farmStateTotal != null) {
              farmStateTotal.isChecked = state.isChecked;
            }
          })
        }
      });
    });
    this.filter();
  }

  private filter() {
    this.matrixFarms.forEach(farm => {
      farm.stateGroupTotals.forEach(farmStateGroupTotal => {
        farmStateGroupTotal.stateTotals.forEach(farmStateTotal => {
          let turbines = farm.devices.filter(o => o.stateId == farmStateTotal.stateId);
          if (turbines) {
            turbines.map(turb => turb.isChecked = farmStateTotal.isChecked);
          }
        });
      })
    });
  }
}
/**
 * 风机型号ID和矩阵关系映射
 *
 * @export
 * @interface MatrixRelationMap
 */
export interface MatrixRelationMap {
  [modelId: number]: MatrixRelation;
}
export interface MatrixStateGroupMap {
  [groupId: number]: { group: MatrixStateGroup; state: MatrixStateMap }
}
export interface MatrixStateMap {
  [stateId: number]: MatrixState;
}




// WEBPACK FOOTER //
// ./src/app/module/monitor/turbine-matrix/turbine-matrix.component.ts